package fr.inserm.umr915.vcfserver.vcf;

import java.util.Comparator;

import com.sleepycat.bind.tuple.TupleBinding;
import com.sleepycat.bind.tuple.TupleInput;
import com.sleepycat.bind.tuple.TupleOutput;
import com.sleepycat.je.DatabaseEntry;

import fr.inserm.umr915.vcfserver.bio.Position;



/***************
 * Mutation
*
*/
public class Mutation implements Comparable<Mutation>
	{
	private Position chrompos;
	private String ref;
	private String alt;
	public Mutation(Position chrompos,String ref,String alt)
		{
		this.chrompos=chrompos;
		this.ref=ref;
		this.alt=alt;
		}
	
	public Position getChromPos() {
		return chrompos;
		}

	public String getChromosome() {
		return getChromPos().getChromosome();
		}

	public int getPosition() {
		return getChromPos().getPosition();
		}

	public String getRef()
		{
		return ref;
		}
	
	public String getAlt()
		{
		return alt;
		}
	
	private static boolean isATGC(String s)
		{
		if(s.length()!=1) return false;
		char c=Character.toUpperCase(s.charAt(0));
		return c=='A' || c=='T' || c=='G' || c=='C';
		}
	
	public boolean isSubstitution()
		{
		return isATGC(getAlt()) && isATGC(getRef());
		}
	
	public final boolean isIndel()
		{
		return !isSubstitution();
		}
	
	
	@Override
	public int hashCode()
		{
		final int prime = 31;
		int result = 1;
		result = prime * result + alt.hashCode();
		result = prime * result + chrompos.hashCode();
		result = prime * result + ref.hashCode();
		return result;
		}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Mutation other = (Mutation) obj;
		return chrompos.equals(other.chrompos) &&
			ref.equalsIgnoreCase(other.ref) &&
			alt.equalsIgnoreCase(other.alt)
			;
		}

	@Override
	public int compareTo(Mutation o)
		{
		int i= getChromPos().compareTo(o.getChromPos());
		if(i!=0) return i;
		i= getRef().compareToIgnoreCase(o.getRef());
		if(i!=0) return i;
		i= getAlt().compareToIgnoreCase(o.getAlt());
		return i;
		}
	
	@Override
	public String toString() {
		return getChromPos().toString()+" "+getRef()+"/"+getAlt();
		}
	
	/** ByteSorter for BDB */
	static public class ByteSorter
		implements Comparator<byte[]>
		{
		public ByteSorter()
			{

			}
		@Override
		public int compare(byte[] o1, byte[] o2)
			{
			Binding bind=new Binding();
			DatabaseEntry e1=new DatabaseEntry(o1);
			DatabaseEntry e2=new DatabaseEntry(o2);
			Mutation m1=bind.entryToObject(e1);
			Mutation m2=bind.entryToObject(e2);
			return m1.compareTo(m2);
			}
		}
		
	/** Data binding for BDB */
	static public class Binding
		extends TupleBinding<Mutation>
		{
		private Position.Binding posBinding=new Position.Binding();
		@Override
		public Mutation entryToObject(TupleInput in)
			{
			Position pos=this.posBinding.entryToObject(in);
			String ref=in.readString();
			String alt=in.readString();
			return new Mutation(pos, ref, alt);
			}
		@Override
		public void objectToEntry(Mutation o, TupleOutput out)
			{
			this.posBinding.objectToEntry(o.getChromPos(), out);
			out.writeString(o.getRef());
			out.writeString(o.getAlt());
			}
		}
	}